package com.ruoyi.project.fusion.algorithms;

import com.ruoyi.project.fusion.domain.PriceAggInfo;
import com.ruoyi.project.fusion.domain.PriceScores;
import com.ruoyi.project.fusion.utils.ComputeUtils;

import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;
import java.util.Map;
import java.util.stream.Collectors;

public class PriceAlgorithm {
    public List<PriceScores> compute(List<PriceAggInfo> priceAggInfos) {
        List<PriceScores> scoresList = new ArrayList<>();

        // 按照 chainType、scenario、product 分组
        Map<List<String>, List<PriceAggInfo>> groupedInfos = priceAggInfos.stream()
                .collect(Collectors.groupingBy(info -> Arrays.asList(
                        info.getChainType(),
                        info.getScenario(),
                        info.getProduct(),
                        info.getEvent()
                )));

        for (Map.Entry<List<String>, List<PriceAggInfo>> entry : groupedInfos.entrySet()) {
            List<PriceAggInfo> group = entry.getValue();

            // 归一化数据
            List<Double> normalizedProductionLineCount = ComputeUtils.normalizeValues(group.stream().map(PriceAggInfo::getAvgProductionLineCount).collect(Collectors.toList()));
            List<Double> normalizedEquipmentCount = ComputeUtils.normalizeValues(group.stream().map(PriceAggInfo::getAvgEquipmentCount).collect(Collectors.toList()));
            List<Double> normalizedEquipmentAutomationLevel = ComputeUtils.normalizeValues(group.stream().map(PriceAggInfo::getAvgEquipmentAutomationLevel).collect(Collectors.toList()));
            List<Double> normalizedMonthlyCapacity = ComputeUtils.normalizeValues(group.stream().map(PriceAggInfo::getAvgMonthlyCapacity).collect(Collectors.toList()));
            List<Double> normalizedMonthlyUtilizationRate = ComputeUtils.normalizeValues(group.stream().map(PriceAggInfo::getAvgMonthlyUtilizationRate).collect(Collectors.toList()));
            List<Double> normalizedAverageProductionCycle = ComputeUtils.normalizeValues(group.stream().map(PriceAggInfo::getAvgAverageProductionCycle).collect(Collectors.toList()));
            List<Double> normalizedEquipmentFailureRate = ComputeUtils.normalizeValues(group.stream().map(PriceAggInfo::getAvgEquipmentFailureRate).collect(Collectors.toList()));

            // 计算各项指标的标准差
            double stdDevProductionLineCount = ComputeUtils.calculateStandardDeviation(normalizedProductionLineCount);
            double stdDevEquipmentCount = ComputeUtils.calculateStandardDeviation(normalizedEquipmentCount);
            double stdDevEquipmentAutomationLevel = ComputeUtils.calculateStandardDeviation(normalizedEquipmentAutomationLevel);
            double stdDevMonthlyCapacity = ComputeUtils.calculateStandardDeviation(normalizedMonthlyCapacity);
            double stdDevMonthlyUtilizationRate = ComputeUtils.calculateStandardDeviation(normalizedMonthlyUtilizationRate);
            double stdDevAverageProductionCycle = ComputeUtils.calculateStandardDeviation(normalizedAverageProductionCycle);
            double stdDevEquipmentFailureRate = ComputeUtils.calculateStandardDeviation(normalizedEquipmentFailureRate);

            // 计算总标准差
            double totalStdDev = stdDevProductionLineCount + stdDevEquipmentCount + stdDevEquipmentAutomationLevel + stdDevMonthlyCapacity +
                    stdDevMonthlyUtilizationRate + stdDevAverageProductionCycle + stdDevEquipmentFailureRate;

            // 计算权重
            double weightProductionLineCount = (totalStdDev == 0) ? 0.1428 : stdDevProductionLineCount / totalStdDev;
            double weightEquipmentCount = (totalStdDev == 0) ? 0.1428 : stdDevEquipmentCount / totalStdDev;
            double weightEquipmentAutomationLevel = (totalStdDev == 0) ? 0.1428 : stdDevEquipmentAutomationLevel / totalStdDev;
            double weightMonthlyCapacity = (totalStdDev == 0) ? 0.1428 : stdDevMonthlyCapacity / totalStdDev;
            double weightMonthlyUtilizationRate = (totalStdDev == 0) ? 0.1428 : stdDevMonthlyUtilizationRate / totalStdDev;
            double weightAverageProductionCycle = (totalStdDev == 0) ? 0.1428 : stdDevAverageProductionCycle / totalStdDev;
            double weightEquipmentFailureRate = (totalStdDev == 0) ? 0.1428 : stdDevEquipmentFailureRate / totalStdDev;

            // 计算分数
            for (int i = 0; i < group.size(); i++) {
                PriceAggInfo info = group.get(i);

                double score = (normalizedProductionLineCount.get(i) * weightProductionLineCount) +
                        (normalizedEquipmentCount.get(i) * weightEquipmentCount) +
                        (normalizedEquipmentAutomationLevel.get(i) * weightEquipmentAutomationLevel) +
                        (normalizedMonthlyCapacity.get(i) * weightMonthlyCapacity) +
                        (normalizedMonthlyUtilizationRate.get(i) * weightMonthlyUtilizationRate) +
                        (normalizedAverageProductionCycle.get(i) * weightAverageProductionCycle) +
                        (normalizedEquipmentFailureRate.get(i) * weightEquipmentFailureRate);

                PriceScores priceScore = new PriceScores();
                priceScore.setChainType(info.getChainType());
                priceScore.setEnterpriseName(info.getEnterpriseName());
                priceScore.setScenario(info.getScenario());
                priceScore.setProduct(info.getProduct());
                priceScore.setEvent(info.getEvent());
                priceScore.setScore(ComputeUtils.roundToTwoDecimalPlaces((float) score));

                scoresList.add(priceScore);
            }
        }

        return scoresList;
    }
}
